<?php
namespace App\Http\Logic;

use App\Models\SwtIdentity;
use App\Models\User;
use App\Services\AdminService;
use App\Services\OpenImService;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;

class AuthLogic extends BaseLogic
{
    public static function register(string $email, string $password, int $country_id, int $code) : array | bool
    {
        if(!Cache::has('email_code_' . $email)) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        if (Cache::get('email_code_' . $email) != $code) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        DB::beginTransaction();
        try {
            $user = User::create([
                'email'      => $email,
                'name'       => 'User_' . Str::random(6),
                'country_id' => $country_id,
                'password'   => Hash::make($password),
            ]);

            $res = TradeLogic::createTrade($user -> id);

            if(!$res) {
                throw new \Exception(self::$error);
            }

            $token = $user->createToken('auth_token')->plainTextToken;

            Cache::forget('email_code_' . $email);

            DB::commit();
            return [
                'access_token' => $token,
                'token_type'   => 'Bearer',
                'user'         => $user
            ];
        } catch(\Exception $e) {
            DB::rollBack();
            self::$error = $e -> getMessage();
            return false;
        }
    }

    public static function registerByPhone(string $phone, int|string $country_id) : array|bool
    {
        DB::beginTransaction();
        try {

            $res = AdminService::getUserInfo($phone);

            if($res['code'] != 1) {
                throw new \Exception('未找到商城用户');
            }

            $nickname = 'User_' . Str::random(6);

            $user = User::create([
                'phone'         => $phone,
                'name'          => $nickname,
                'shop_user_id'  => $res['data']['id']
            ]);

            $res = TradeLogic::createTrade($user -> id);

            if(!$res) {
                throw new \Exception(self::$error);
            }

            $res = OpenImService::initUser([[
                "id"      => $user->id,
                "name"    => $nickname,
                "faceURL" => ""
            ]]);

            if($res['errCode'] != 0) {
                throw new \Exception($res['errMsg']);
            }

            $res = OpenImService::getUserToken($user -> id);

            if($res['errCode'] != 0) {
                throw new \Exception($res['errMsg']);
            }

            $token = $user->createToken('auth_token')->plainTextToken;

            DB::commit();
            return [
                'access_token' => $token,
                'token_type'   => 'Bearer',
                'user'         => $user,
                'im_token'     => $res['data']['token'],
            ];
        } catch(\Exception $e) {
            DB::rollBack();
            self::$error = $e -> getMessage();
            return false;
        }
    }

    public static function login(array $params) : bool|array
    {
        $user = User::firstWhere('email', $params['email']);

        if(!$user) {
            self::$error = __('auth.user_not_found');
            return false;
        }

        if(!Hash::check($params['password'], $user->password)) {
            self::$error = __('auth.password_error');
            return false;
        }

        $token = $user->createToken('auth_token')->plainTextToken;

        return [
            'access_token' => $token,
            'token_type'   => 'Bearer',
            'user'         => $user
        ];
    }

    public static function phoneLogin(string $phone, string $code, int|string $country_id) : bool|array
    {
        if(!Cache::has('sms_code_' . $phone)) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        if (Cache::get('sms_code_' . $phone) != $code) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        $user = User::firstWhere('phone', $phone);

        if(!$user) {
           return self::registerByPhone($phone, $country_id);
        }

        $res = OpenImService::getUserToken($user -> id);

        if($res['errCode'] != 0) {
            throw new \Exception($res['errMsg']);
        }

        $token = $user->createToken('auth_token')->plainTextToken;

        Cache::forget('sms_code_' . $phone);

        return [
            'access_token' => $token,
            'im_token'     => $res['data']['token'],
            'token_type'   => 'Bearer',
            'user'         => $user -> toArray()
        ];
    }

    public static function getImToken($user_id)
    {
        $res = OpenImService::getUserToken($user_id);

        if($res['errCode'] != 0) {
            self::$error = $res['errMsg'];
            return false;
        }

        return ['im_token' => $res['data']['token'], 'user' => ['id' => $user_id]];
    }

    public static function setPassword(string $code, int $user_id, string $password) : bool {
        $user = User::find($user_id);

        if(!$user) {
            self::$error = __('auth.user_not_found');
            return false;
        }

        if(!Cache::has('sms_code_set_password_' . $user->phone)) {
            self::$error = __('auth.phone_error');
            return false;
        }

        if (Cache::get('sms_code_set_password_' . $user->phone) != $code) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        $user -> password = Hash::make($password);

        Cache::forget('sms_code_set_password_' . $user->phone);

        return $user->save();
    }

    public static function updatePassword(array $params) : bool
    {
        $user = User::find($params['user_id']);

        if(!$user) {
            self::$error = __('auth.user_not_found');
            return false;
        }

        if(!Hash::check($params['old_password'], $user->password)) {
            self::$error = __('auth.password_error');
            return false;
        }

        $user -> password = Hash::make($params['password']);

        $res = $user->save();

        return $res;
    }

    public static function forgetPassword(array $params) : bool
    {
        if(!Cache::has('email_code_forget_password_' . $params['email'])) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        if (Cache::get('email_code_forget_password_' . $params['email']) != $params['code']) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        $res = User::where('email', $params['email']) -> update(['password' => Hash::make($params['password'])]);

        if(!$res) {
            self::$error = __('auth.update_fail');
            return false;
        }

        Cache::forget('email_code_forget_password_' . $params['email']);

        return true;
    }

    public static function setPayPassword(array $params) : bool
    {
        $user = User::find($params['user_id']);

        if(!$user) {
            self::$error = __('auth.user_not_found');
            return false;
        }

        if (Cache::get('sms_code_pay_password_' . $user->phone) != $params['code']) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        $user -> pay_password = Hash::make($params['pay_password']);

        $res = $user->save();

        Cache::forget('sms_code_pay_password_' . $user->phone);

        return $res;
    }
    public static function updatePayPassword(array $params) : bool {
        $user = User::find($params['user_id']);

        if(!$user) {
            self::$error = __('auth.user_not_found');
            return false;
        }

        if(!Hash::check($params['old_pay_password'], $user->pay_password)) {
            self::$error = __('auth.old_password_error');
            return false;
        }

        $user -> pay_password = Hash::make($params['pay_password']);

        $res = $user->save();

        return $res;
    }
    public static function checkPhoneCode(string $code, int $user_id) : bool {
        $user = User::find($user_id);

        if(Cache::get('sms_code_change_phone_' . $user -> phone) != $code) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        Cache::forget('sms_code_change_phone_' . $user->phone);

        return true;
    }
    public static function updatePhone(string $phone, string $code, int $user_id) : bool {
        $user = User::find($user_id);

        if(Cache::get('sms_code_change_phone_' . $phone) != $code) {
            self::$error = __('auth.sms_code_error');
            return false;
        }

        $user -> phone = $phone;

        $res = $user->save();

        Cache::forget('sms_code_change_phone_' . $phone);

        return $res;
    }

    public static function getUserInfo(int $user_id) : array
    {
        $data = User::with('identity') -> where('id', $user_id) -> first() -> toArray();

        $data['has_password'] = auth() -> user() -> password ? 1 : 0;

        $data['has_pay_password'] = auth() -> user() -> pay_password ? 1 : 0;

        $data['country'] = $data['country_id'] ? UtilLogic::getCountryInfo($data['country_id']) : '';

        return $data;
    }

    public static function updateUserInfo(int $user_id, array $params) : bool {

        $user = User::find($user_id);

        $res = $user -> update($params);

        return $res;
    }

    public static function addUserIdentity(array $params) : bool
    {
        $res = SwtIdentity::where('user_id', $params['user_id']) -> where('type', $params['type']) -> first();

        if($res) {
            self::$error = __('auth.user_already_exist');
            return false;
        }

        $res = SwtIdentity::create($params);

        if(!$res) {
            self::$error = __('auth.identity_add_error');
            return false;
        }

        return true;
    }

    public static function editUserIdentity(array $params, int $id) : bool
    {
        $res = SwtIdentity::where('id', $id) -> first();

        if(!$res) {
            self::$error = __('auth.user_not_found');
            return false;
        }

        $params['status'] = 0;

        $res = SwtIdentity::where('id', $id) -> update($params);

        if(!$res) {
            self::$error = __('auth.identity_add_error');
            return false;
        }

        return true;
    }
}
